package FINAL.GUI;

import java.awt.EventQueue;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.JButton;

import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.List;
import java.util.Random;

import javax.swing.JLabel;

import FINAL.CONSTANT;
import FINAL.Read_file_to_matrix;
import FINAL.find_monitors.Calculator_Incoming_edges;
import FINAL.find_monitors.Inter_monitor_distance;
import FINAL.find_monitors.NI_and_DIS;
import FINAL.find_monitors.RandomMonitors;
import FINAL.find_rumors.Calculaotr_distance;
import FINAL.xd_tap_C.GSSS;

import javax.swing.JTextField;
import javax.swing.JComboBox;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JSplitPane;

import java.awt.Component;

import javax.swing.Box;
import javax.swing.JSeparator;
import javax.swing.JCheckBox;

public class GUI1 extends JFrame {

	private JPanel contentPane;
	private JLabel lblTrngThiCha;
	private int[][] matrix;
	int[] tap_gs_duong, tap_gs_am;
	private int method_find_monitor = 0;
	private JButton btnNewButton_1;
	private final JTextField textField = new JTextField();
	private final JLabel lblNhpK = new JLabel("Nhập k:");
	private final JComboBox comboBox = new JComboBox();
	private final JButton btnNewButton_2 = new JButton("B3.In n kết quả");
	private final JLabel lblNhpN = new JLabel("Nhập n:");
	private final JTextField textField_1 = new JTextField();
	private final JLabel lblNhpD = new JLabel("Nhập d:");
	private final JTextField textField_2 = new JTextField();
	private final JSeparator separator = new JSeparator();
	private final JSeparator separator_1 = new JSeparator();
	private final JSeparator separator_2 = new JSeparator();
	private final JButton btnNewButton_3 = new JButton("Xác định tập C");
	static int[] list_rd = new int[CONSTANT.SIZE];
	static int[] list_rd_backup = new int[CONSTANT.SIZE];
	private final JCheckBox chckbxXoTrn = new JCheckBox("xáo trộn");
	private boolean xaotron = true;

	/**
	 * Launch the application.
	 */
	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				for (int i = 0; i < CONSTANT.SIZE; i++) {
					list_rd[i] = i;
				}
				try {
					GUI1 frame = new GUI1();
					frame.setVisible(true);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

	/**
	 * Create the frame.
	 */
	public GUI1() {
		textField_2.setBounds(251, 111, 37, 20);
		textField_2.setColumns(10);
		textField_1.setBounds(251, 148, 37, 20);
		textField_1.setColumns(10);
		textField.setBounds(251, 80, 37, 20);
		textField.setColumns(10);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setBounds(100, 100, 469, 289);
		contentPane = new JPanel();
		contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
		setContentPane(contentPane);
		contentPane.setLayout(null);

		JButton btnNewButton = new JButton("B1.Đọc file dữ liệu");
		btnNewButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				matrix = Read_file_to_matrix.read_file_to_matrix();
				lblTrngThiCha.setText("Trạng thái: Đã đọc file dữ liệu");
			}
		});
		btnNewButton.setBounds(38, 11, 133, 41);
		contentPane.add(btnNewButton);

		lblTrngThiCha = new JLabel("Trạng thái: Chưa đọc file dữ liệu");
		lblTrngThiCha.setBounds(198, 24, 203, 14);
		contentPane.add(lblTrngThiCha);

		btnNewButton_1 = new JButton("B2.Chọn k node g/s");
		btnNewButton_1.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				int k = Integer.parseInt(textField.getText());
				int d;
				try {
					d = Integer.parseInt(textField_2.getText());
				} catch (Exception ex) {
					d = 0;
				}
				System.out.println("Tìm " + k + " node gs với d =  " + d);
				find_monitors(k, d, method_find_monitor);
			}
		});
		btnNewButton_1.setBounds(38, 74, 133, 33);
		contentPane.add(btnNewButton_1);

		contentPane.add(textField);
		lblNhpK.setBounds(198, 83, 63, 14);

		contentPane.add(lblNhpK);
		comboBox.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				JComboBox cb = (JComboBox) e.getSource();
				method_find_monitor = cb.getSelectedIndex();
			}
		});
		comboBox.setModel(new DefaultComboBoxModel(new String[] { "Random",
				"Incoming edges", "Inter-monitor Distance", "IN and DIS" }));
		comboBox.setBounds(318, 80, 103, 20);

		contentPane.add(comboBox);
		btnNewButton_2.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				/**
				 * tính khoảng cách của tất cả các node đến tập giám sát âm và
				 * dương
				 */
				int[][] kc_gs_duong = Calculaotr_distance
						.tinh_kc_den_tap_gs_all(matrix, tap_gs_duong);
				int[][] kc_gs_am = Calculaotr_distance.tinh_kc_den_tap_gs_all(
						matrix, tap_gs_am);
				BufferedWriter bw = null;
				try {
					File file = new File("E:/DATA/k20d0NIDIS.txt");
					if (!file.exists()) {
						file.createNewFile();
					}
					FileWriter fw = new FileWriter(file.getAbsoluteFile());
					bw = new BufferedWriter(fw);

					// for (int i = 0; i < kc_gs_duong[0].length; i++) {
					// bw.write(kc_gs_duong[0][i] + "\t");
					// }
					// bw.write("\n");
					// for (int i = 0; i < kc_gs_duong[1].length; i++) {
					// bw.write(kc_gs_duong[1][i] + "\t");
					// }
					// bw.write("\n");
					// for (int i = 0; i < kc_gs_am[0].length; i++) {
					// bw.write(kc_gs_am[0][i] + "\t");
					// }
					// bw.write("\n");
					// for (int i = 0; i < kc_gs_am[1].length; i++) {
					// bw.write(kc_gs_am[1][i] + "\t");
					// }
					// bw.write("\n");
					// ///////////////////////////////////////////////
					/**
					 * sắp xếp lại mảng kc_gs_duong
					 */
					for (int i = kc_gs_duong[1].length - 1; i >= 0; i--) {
						for (int j = i - 1; j >= 0; j--) {
							if (kc_gs_duong[1][i] == -1
									&& kc_gs_duong[1][j] > 0) {
								// Giữ nguyên
							} else if (kc_gs_duong[1][i] < kc_gs_duong[1][j]) {
								// đổi chỗ
								int[][] tmp = new int[2][1];
								tmp[0][0] = kc_gs_duong[0][i];
								tmp[1][0] = kc_gs_duong[1][i];
								kc_gs_duong[0][i] = kc_gs_duong[0][j];
								kc_gs_duong[1][i] = kc_gs_duong[1][j];
								kc_gs_duong[0][j] = tmp[0][0];
								kc_gs_duong[1][j] = tmp[1][0];
							} else if (kc_gs_duong[1][i] == kc_gs_duong[1][j]) {
								// so sánh kc đến tập gs âm nữa
								if (kc_gs_am[1][j] == -1) {
									// giữ nguyên
								} else if (kc_gs_am[1][j] != -1
										&& kc_gs_am[1][i] == -1) {
									// đổi chỗ
									int[][] tmp = new int[2][1];
									tmp[0][0] = kc_gs_duong[0][i];
									tmp[1][0] = kc_gs_duong[1][i];
									kc_gs_duong[0][i] = kc_gs_duong[0][j];
									kc_gs_duong[1][i] = kc_gs_duong[1][j];
									kc_gs_duong[0][j] = tmp[0][0];
									kc_gs_duong[1][j] = tmp[1][0];
								} else if (kc_gs_am[1][i] > kc_gs_am[1][j]) {
									// đổi chỗ
									int[][] tmp = new int[2][1];
									tmp[0][0] = kc_gs_duong[0][i];
									tmp[1][0] = kc_gs_duong[1][i];
									kc_gs_duong[0][i] = kc_gs_duong[0][j];
									kc_gs_duong[1][i] = kc_gs_duong[1][j];
									kc_gs_duong[0][j] = tmp[0][0];
									kc_gs_duong[1][j] = tmp[1][0];
								}
							}
						}
					}
					for (int i = 0; i < kc_gs_duong[0].length; i++) {
						bw.write(kc_gs_duong[0][i] + "\t");
					}
					bw.write("\n");
					for (int i = 0; i < kc_gs_duong[1].length; i++) {
						bw.write(kc_gs_duong[1][i] + "\t");
					}
					System.out.println("Ghi file xong rồi");
				} catch (Exception e) {
					System.err.print("Ex GUI1");
				} finally {
					try {
						bw.close();
					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
			}
		});
		btnNewButton_2.setBounds(38, 142, 133, 33);

		contentPane.add(btnNewButton_2);
		lblNhpN.setBounds(198, 151, 63, 14);

		contentPane.add(lblNhpN);

		contentPane.add(textField_1);
		lblNhpD.setBounds(198, 108, 46, 14);

		contentPane.add(lblNhpD);

		contentPane.add(textField_2);
		separator.setBounds(38, 183, 385, 2);

		contentPane.add(separator);
		separator_1.setBounds(36, 63, 385, 2);

		contentPane.add(separator_1);
		separator_2.setBounds(36, 133, 385, 2);

		contentPane.add(separator_2);
		btnNewButton_3.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				List<Integer> Cset = GSSS.C(matrix, tap_gs_duong);
				System.out.println("\n Tập C: ");
				System.out.println("\n Size C: " + Cset.size());
				for (int i = 0; i < Cset.size(); i++) {
					System.out.print("  " + Cset.get(i));
				}
			}
		});
		btnNewButton_3.setBounds(38, 200, 133, 33);

		contentPane.add(btnNewButton_3);
		chckbxXoTrn.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				JCheckBox checkb = (JCheckBox) arg0.getSource();
				xaotron = checkb.isSelected();
			}
		});
		chckbxXoTrn.setBounds(318, 110, 97, 23);

		contentPane.add(chckbxXoTrn);
	}

	private void find_monitors(int k, int d, int method) {
		// giả sử tạo tin đồn, để xác định tập gs âm và dương
		// int[] kha_nang_lan_truyen = Calculaotr_distance.A(1548, matrix);
		int[] kha_nang_lan_truyen = Calculaotr_distance.A(1259, matrix);
		int count = 0;
		for (int i = 0; i < kha_nang_lan_truyen.length; i++) {
			if (kha_nang_lan_truyen[i] == -1)
				count++;

		}
		System.err.println("################## " + count + "/"
				+ kha_nang_lan_truyen.length);
		// ////////////////////////////////////////////////
		int[] monitors = null;
		switch (method) {
		case 0:
			monitors = RandomMonitors.random(k);
			break;
		case 1:
			monitors = Calculator_Incoming_edges.IN(k);
			break;
		case 2:

			if (xaotron) {
				shuffleArray(list_rd);
			}
			for (int i = 0; i < list_rd.length; i++) {
				list_rd_backup[i] = list_rd[i];
			}
			monitors = Inter_monitor_distance.InterMonitorDistance(k, d,
					matrix, list_rd);
			for (int i = 0; i < list_rd.length; i++) {
				list_rd[i] = list_rd_backup[i];
			}
			break;
		case 3:
			monitors = NI_and_DIS.NIandDIS(k, d, matrix);
			break;
		default:
			break;
		}

		int gs_d = 0, gs_a = 0;
		for (int i = 0; i < monitors.length; i++) {
			System.out.println(monitors[i] + " hehe: "
					+ kha_nang_lan_truyen[monitors[i]]);
			if (kha_nang_lan_truyen[monitors[i]] == -1) {
				gs_a++;
			} else {
				gs_d++;
			}
		}

		tap_gs_am = new int[gs_a];
		tap_gs_duong = new int[gs_d];
		int tmp_a = 0, tmp_d = 0;
		for (int i = 0; i < monitors.length; i++) {
			if (kha_nang_lan_truyen[monitors[i]] == -1) {
				tap_gs_am[tmp_a] = monitors[i];
				tmp_a++;
			} else {
				tap_gs_duong[tmp_d] = monitors[i];
				tmp_d++;
			}
		}
		for (int i = 0; i < tap_gs_am.length; i++) {
			System.out.println("GS am: " + tap_gs_am[i]);
		}
		for (int i = 0; i < tap_gs_duong.length; i++) {
			System.out.println("GS duong: " + tap_gs_duong[i]);
		}
	}

	public static void shuffleArray(int[] ar) {
		Random rnd = new Random();
		for (int i = ar.length - 1; i > 0; i--) {
			int index = rnd.nextInt(i + 1);
			// Simple swap
			int a = ar[index];
			ar[index] = ar[i];
			ar[i] = a;
		}
	}
}
